#pragma once


#include "Macros.h"


using namespace std;

struct DLLEXPIMP RangeBox
{
	RangeBox() 
	{
		dXmin = dYmin = 1E20;
		dXmax = dYmax = -1E20;
	}
	
	RangeBox(double xmin, double ymin, double xmax, double ymax) 
	{
		dXmin = xmin;
		dYmin = ymin;
		dXmax = xmax;
		dYmax = ymax;
	}

	double GetWidth() { return (dXmax - dXmin);}
	double GetHeight(){ return (dYmax - dYmin);}
	void GetCenterPoint(double& dCX, double& dCY)
	{
		dCX = dXmin + GetWidth() / 2;
		dCY = dYmin + GetHeight() / 2;
	}

	double dXmin;
	double dYmin;
	double dXmax;
	double dYmax;
};

class DLLEXPIMP CGeoFeature
{
public:
	CGeoFeature(){};
	virtual ~CGeoFeature() {};
	virtual RangeBox GetRangeBox(bool bRecaculate = false) = 0;
	virtual void Display(CDC* pDC) = 0;
	virtual void SetStyle(int s1, int s2, int s3) = 0;
};

class DLLEXPIMP CGeoPoint2 : public CGeoFeature
{
public:
	CGeoPoint2(double dx, double dy, double dex = 0.0f, double dey = 0.0f) : x(dx), y(dy), ex(dex), ey(dey) {}
	virtual RangeBox GetRangeBox(bool bRecaculate = false) { return RangeBox(x, y, x, y); }
	virtual void Display(CDC* pDC) { };
	virtual void SetStyle(int s1, int s2, int s3) {};

	double ex, ey;	// represent the longtitude/latitude point
	double x,y;
};

class DLLEXPIMP CGeoLine2 : public CGeoFeature
{
public:
	CGeoLine2() : m_style(PS_SOLID), m_iWidth(1),m_color(RGB(0,0,0)) {}
	CGeoLine2(const CGeoLine2& ref) { *this = ref; }

	virtual void Display(CDC* pDC);

	virtual RangeBox GetRangeBox(bool bRecaculate = false);
	
	// modify
	void AddPoint(const CGeoPoint2& pt) { m_vecPts.push_back(pt); }
	void SetStyle(int s1, int s2, int s3);

	// query
	size_t GetSize() { return m_vecPts.size(); }
	CGeoPoint2 GetAt(size_t pos);
	bool InWindow();

private:
	RangeBox	m_rangebox;
	std::vector<CGeoPoint2> m_vecPts;	
	int m_style;
	int m_iWidth;
	COLORREF m_color;
};


class DLLEXPIMP CGeoLayer
{
public:
	CGeoLayer(std::string strLayerName);
	~CGeoLayer(void);
	std::string GetName() { return m_strLayerName; }
	void AddFeature(CGeoFeature* pFeature) { m_vecFeature.push_back(pFeature); }
	virtual void Display(CDC* pDC);

	// query
	size_t GetSize() { return m_vecFeature.size(); }
	RangeBox GetRangeBox(bool bRecaculate = false);
private:
	RangeBox	m_rangebox;
	std::vector<CGeoFeature*> m_vecFeature;
	std::string	m_strLayerName;
};


class DLLEXPIMP CGeoMap
{
public:
	CGeoMap(std::string strMapName);
	~CGeoMap(void);

	CGeoLayer* GetLayer(std::string strLayerName);
	CGeoLayer* GetLayer(size_t idx) { return m_vecLayer[idx]; }
		
	virtual void Display(CDC* pDC);
	void Reset();
	void DeleteAll();

	// query
	size_t GetSize() { return m_vecLayer.size(); }

	// range box
	RangeBox GetRangeBox(bool bRecaculate = false);

	void SetMapScale(double dScale) { m_dScale = dScale; }
private:
	RangeBox m_rangebox;
	std::vector<CGeoLayer*> m_vecLayer;
	std::string m_strMapName;
	double	m_dScale;
};
